package com.block.common.service.impl;

import cn.hutool.core.util.StrUtil;
import com.block.common.constant.RedisKeyConstant;
import com.block.common.enums.InfoTypeEnum;
import com.block.common.exception.NotifyExceptionService;
import com.block.common.model.dto.SourceCountDTO;
import com.block.common.service.*;
import com.block.db.entity.SourceBaseInfo;
import com.block.db.entity.SourcePushResultInfo;
import com.block.db.mapper.SourcePushResultInfoMapper;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;

@Service
public class SourcePushResultInfoCommonService implements ISourcePushResultInfoCommonService {

    private static final Logger log = LogFactory.getSourceLog();

    @Resource
    SourcePushResultInfoMapper sourcePushResultInfoMapper;
    @Autowired
    ISourceDataCallbackLogService sourceDataCallbackLogService;
    @Autowired
    ISourceDataCountInfoService sourceDataCountInfoService;
    @Autowired
    ISourceBaseInfoService sourceBaseInfoService;
    @Autowired
    NotifyExceptionService notifyExceptionService;
    @Autowired
    StringRedisTemplate stringRedisTemplate;

    /**
     * 扣量 逻辑处理
     * 第二种方式
     * @param pushResultInfo
     * @return true 扣量  false 不扣量
     *
     */
    @Override
    public boolean lessNumberHandle2(SourcePushResultInfo pushResultInfo){

        // 异步执行统计的逻辑
        // 扣量计算
        try {

            SourceBaseInfo sourceBaseInfo = sourceBaseInfoService.getSourceBaseInfoByCode(pushResultInfo.getChannelCode());
            if (BigDecimal.ONE.compareTo(sourceBaseInfo.getLessRate()) < 0){
                log.info("【机构推送】回调通知，扣量设置错误【channelName】{}【lessRate】{}",
                        sourceBaseInfo.getChannelName(), sourceBaseInfo.getLessRate());
                String message = StrUtil.format("渠道扣量比设置错误【channelCode】{}【channelName】{}【lessRate】{}",
                        sourceBaseInfo.getChannelCode(), sourceBaseInfo.getChannelName(), sourceBaseInfo.getLessRate());
                throw new RuntimeException(message);
            }

            // 扣量 计算
            String dateInfo = LocalDate.now().toString();
            String successNumberKey = StrUtil.format(RedisKeyConstant.SOURCE_SHOULD_SUCCESS_NUMBER, dateInfo, sourceBaseInfo.getChannelCode());
            String noticeNumberKey = StrUtil.format(RedisKeyConstant.SOURCE_NOTICE_SUCCESS_NUMBER, dateInfo, sourceBaseInfo.getChannelCode());
            String successNumberValue = stringRedisTemplate.opsForValue().get(successNumberKey);
            String noticeNumberValue = stringRedisTemplate.opsForValue().get(noticeNumberKey);

            // 查询到 通知数据的默认值
            if (StrUtil.isEmpty(successNumberValue)){
                successNumberValue = "0";
            }
            if (StrUtil.isEmpty(noticeNumberValue)){
                noticeNumberValue = "0";
            }

            // 结算比例
            BigDecimal settleRate = BigDecimal.ONE.subtract(sourceBaseInfo.getLessRate());

            // 该条记录推送，记录+1
            BigDecimal newSuccessNumber = new BigDecimal(successNumberValue).add(BigDecimal.ONE);

            // 应该结算通知量
            BigDecimal shouldNoticeNumber = newSuccessNumber.multiply(settleRate).setScale(0, RoundingMode.DOWN);
            boolean notToNotice = shouldNoticeNumber.compareTo(new BigDecimal(noticeNumberValue)) <= 0;
            log.info("【机构推送】回调通知，扣量判断【channelCode】{}【channelName】{}【notToNotice】{}【successNumberValue】{}【settleRate】{}【shouldNoticeNumber】{}【noticeNumberValue】{}",
                    sourceBaseInfo.getChannelCode(), sourceBaseInfo.getChannelName(), notToNotice, successNumberValue, settleRate, shouldNoticeNumber, noticeNumberValue);

            return notToNotice;
        }catch (Exception exception){
            exception.printStackTrace();
            notifyExceptionService.notifyNoticeInfo("SOURCE_TAKE_OUT_HANDLE", "线索扣量处理异常", "【resultNo】" + pushResultInfo.getId(), exception);
        }
        return true;
    }

    @Async
    @Override
    public void pushResultCount(boolean notToNotice, boolean status, boolean settelStatus, SourcePushResultInfo pushResultInfo){

        try {
            SourceBaseInfo sourceBaseInfo = sourceBaseInfoService.getSourceBaseInfoByCode(pushResultInfo.getChannelCode());
            if (BigDecimal.ONE.compareTo(sourceBaseInfo.getLessRate()) < 0){
                log.info("【机构推送】回调通知，扣量设置错误【channelName】{}【lessRate】{}",
                        sourceBaseInfo.getChannelName(), sourceBaseInfo.getLessRate());
                String message = StrUtil.format("渠道扣量比设置错误【channelCode】{}【channelName】{}【lessRate】{}",
                        sourceBaseInfo.getChannelCode(), sourceBaseInfo.getChannelName(), sourceBaseInfo.getLessRate());
                throw new RuntimeException(message);
            }

            //
            SourcePushResultInfo updateResult = new SourcePushResultInfo();
            updateResult.setId(pushResultInfo.getId());
            updateResult.setRegisterIp(pushResultInfo.getRegisterIp());
            if (status){
                updateResult.setStatus("SUCCESS");
            }
            if (settelStatus){
                updateResult.setSettleStatus("SUCCESS");
            }
            updateResult.setMessage("成功");

            SourceCountDTO sourceCountDTO = new SourceCountDTO(pushResultInfo.getChannelCode(), pushResultInfo.getChannelName());
            sourceCountDTO.setApproveSuccessNumber(1);

            // notToNotice true 扣量 false 不扣量
            if (notToNotice){
                // 该条记录进行扣量
                updateResult.setNoticeFlag(0);
                sourcePushResultInfoMapper.updateById(updateResult);
            }else{
                sourceCountDTO.setNoticeNumber(1);
                // 该条记录不进行扣量
                if (StrUtil.equals(sourceBaseInfo.getType(), InfoTypeEnum.APIB.getValue())){
                    // 回调进行结算
                    // 进行渠道结算通知
                    boolean b = sourceDataCallbackLogService.resultToCallBack(pushResultInfo);
                    if (b) {
                        // 通知成功
                        updateResult.setNoticeFlag(1);
                        sourceCountDTO.setNoticeSuccessNumber(1);
                    }else{
                        // 通知失败
                        updateResult.setNoticeFlag(-1);
                    }
                }else{
                    updateResult.setNoticeFlag(1);
//                // 统计通知成功数量
                    sourceCountDTO.setNoticeSuccessNumber(1);
                }
                // 更新推送结果记录
                sourcePushResultInfoMapper.updateById(updateResult);
            }
            sourceDataCountInfoService.saveSourceCountInfo(sourceCountDTO);
        }catch (Exception exception){
            exception.printStackTrace();
        }
    }

}
